/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Initial Developer of the Original Code is
*   Nick Kreeger
* Portions created by the Initial Developer are Copyright (C) 2006-2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*   Nick Kreeger <nick.kreeger@park.edu>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */

#import "CHMsgService.h"

#import "MessageWindowService.h"
#import "NSString+Utils.h"

#import "CHMsgHeaderSink.h"
#import "CHMsgDBViewService.h"
#import "CHBrowserView.h"

#import "nsIDocShell.h"
#import "nsIDOMWindow.h"
#import "nsIDOMWindowInternal.h"

#import "nsIURI.h"
#import "nsIUrlListener.h"
#import "nsIWeakReference.h"
#import "nscore.h"
#import "nsServiceManagerUtils.h"
#import "nsString.h"

#import "nsIMsgHdr.h"
#import "nsIMsgMailNewsUrl.h"
#import "nsIMimeHeaders.h"
#import "nsIMsgMdnGenerator.h"
#import "nsIMessenger.h"
#import "nsIMessengerOSIntegration.h"
#import "nsIMsgDatabase.h"

#import "nsIRDFDataSource.h"
#import "rdf.h"

#import "nsMsgBaseCID.h"
#import "nsMsgCompCID.h"

//XXX use constants here.
const char kmMsgWindowContractID[] = "@mozilla.org/messenger/mMsgWindow;1";
const char kMsgMailSessionContractID[] = "@mozilla.org/messenger/services/session;1";
const char kMsgAccountManagerContractID[] = "@mozilla.org/messenger/account-manager;1";
//const char kDataSourceContractIDPrefix[] = "@mozilla.org/rdf/datasource;1?name="; // Can't add [] + []
const char kCompositeDataSourceContractID[] = "@mozilla.org/rdf/datasource;1?name=composite-datasource";
const char kAccountManagerDSContractID[] = "@mozilla.org/rdf/datasource;1?name=msgaccountmanager";
const char kFolderDataSourceContractID[] = "@mozilla.org/rdf/datasource;1?name=mailnewsfolders";

//#define MSG_FLAG_READ               0x000001
#define MSG_FLAG_IMAP_DELETED       0x200000
#define MSG_FLAG_MDN_REPORT_NEEDED  0x400000
#define MSG_FLAG_MDN_REPORT_SENT    0x800000
#define MDN_DISPOSE_TYPE_DISPLAYED  0
#define ADDR_DB_LARGE_COMMIT        1
#define MSG_DB_LARGE_COMMIT         1

#pragma mark -

/**
 * This class must remain seperate from CHMsgService because
 * it is destroyed after the URL has finished loading.
 */
class CHUrlListener : public nsIUrlListener
{
public:
  CHUrlListener(CHMsgService* aNotifier);
  virtual ~CHUrlListener();
  
  NS_DECL_NSIURLLISTENER
  NS_DECL_ISUPPORTS
    
private:
  CHMsgService* mNotifier;  // who to inform of changes, weak ref.
};

NS_IMPL_ISUPPORTS1(CHUrlListener, nsIUrlListener)

CHUrlListener::CHUrlListener(CHMsgService* aNotifier)
: mNotifier(aNotifier)
{
}

CHUrlListener::~CHUrlListener()
{
}

NS_IMETHODIMP 
CHUrlListener::OnStartRunningUrl(nsIURI* url)
{
  mNotifier->OnStartRunningUrl();
}

NS_IMETHODIMP
CHUrlListener::OnStopRunningUrl(nsIURI* url, nsresult aExitCode)
{
  mNotifier->OnStopRunningUrl();
}

#pragma mark -

NS_IMPL_ISUPPORTS2(CHMsgService, nsIFolderListener, nsIMsgStatusFeedback);

CHMsgService::CHMsgService()
{
  mMessageWindowService = nil;
  mIsRunningUri = PR_FALSE;
}

CHMsgService::~CHMsgService()
{
  mMessenger = nsnull;
  mCurMsgWindow = nsnull;
  //NS_IF_RELEASE(mMsgWindows);  find out how to relase an array
}

NS_IMETHODIMP 
CHMsgService::Init(MessageWindowService* aMessageWindowService)
{
  nsresult rv;
  
  mMessageWindowService = aMessageWindowService;
  
  //XXX I think I should return if these fail, they are pretty important.
  mMessenger = do_CreateInstance(NS_MESSENGER_CONTRACTID, &rv);
#if DEBUG
  if (NS_FAILED(rv))
    printf("ERROR: Could not get the nsIMessenger service!\n");
#endif

  //XXX kreeger 3/14/2007:
  //    This class needs to work around a service of |nsIMsgWindow| and use it's member
  //    variable to do all the setup work. Or else, single window messages won't work!
  
  nsCOMPtr<nsIMsgMailSession> mailSession = do_GetService(NS_MSGMAILSESSION_CONTRACTID, &rv);
  if (NS_SUCCEEDED(rv))
    mailSession->AddFolderListener(this, nsIFolderListener::intPropertyChanged);
  
  // Paranoia, make sure the service has been started.
  nsCOMPtr<nsIMessengerOSIntegration> osIntegration = do_GetService(NS_MESSENGEROSINTEGRATION_CONTRACTID, &rv);
  NS_ENSURE_SUCCESS(rv, rv);
  
  return rv;
}

NS_IMETHODIMP
CHMsgService::Shutdown()
{
  nsresult rv;
  nsCOMPtr<nsIMsgMailSession> mailSession = do_GetService(NS_MSGMAILSESSION_CONTRACTID, &rv);
  if (NS_SUCCEEDED(rv))
    mailSession->Shutdown();
  
  //XXX something else should happen here.
  return NS_OK;
}

NS_IMETHODIMP
CHMsgService::GetNewMessages(nsIMsgFolder* inMsgFolder)
{
  if (!inMsgFolder)
    return NS_ERROR_FAILURE;
  
  //I don't think I will need this?
  // Whenever we do get new messages, clear the old new messages.
  inMsgFolder->SetBiffState(nsIMsgFolder::nsMsgBiffState_NoMail);
  inMsgFolder->ClearNewMessages();
  
  // This pointer gets destroyed after the URI transaction.
  CHUrlListener* urlListener = new CHUrlListener(this);
  return inMsgFolder->GetNewMessages(mCurMsgWindow, urlListener);
}

NS_IMETHODIMP
CHMsgService::GetNewMessagesForAllServers()
{
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP
CHMsgService::CreateNewFolder()
{
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP
CHMsgService::CreateNewSubfolder()
{
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP     
CHMsgService::OpenUri(const char* aUriSpec)
{
  if (!aUriSpec)
    return NS_ERROR_NULL_POINTER;

  // If there is a URI running in the background, we might lock
  // up the IMAP thread.
  if (mIsRunningUri)
    StopUrls();
  
  return mMessenger->OpenURL(aUriSpec);
}

NS_IMETHODIMP
CHMsgService::StopUrls()
{
  if (mIsRunningUri)
    mCurMsgWindow->StopUrls();
  
  return NS_OK;
}

NS_IMETHODIMP 
CHMsgService::OnMsgLoaded(nsIMsgMailNewsUrl* aUrl, DummyMessageHeader* aDummyMessageHeader)
{
  NS_ENSURE_ARG(aUrl);
  nsresult rv;
  
  nsCOMPtr<nsIMsgFolder> msgFolder;
  aUrl->GetFolder(getter_AddRefs(msgFolder));
  if (!msgFolder)
    return NS_ERROR_FAILURE;
  
  NSString* currentUri = [mMessageWindowService currentMessageUri];
  if (!currentUri)
    return NS_ERROR_UNEXPECTED;
    
  /*
   This might be something important
    if (!(/type=application\/x-message-display/.test(msgURI)))
      msgHdr = messenger.msgHdrFromURI(msgURI);
   */
  
  [mMessageWindowService onMessageLoaded:aDummyMessageHeader];
  
  HandleMDNResponse(aUrl);
  
  nsCOMPtr<nsIMsgFolder> currentMsgFolder = do_QueryInterface(msgFolder, &rv);
  NS_ENSURE_SUCCESS(rv, rv);
  
  nsCOMPtr<nsIMsgDatabase> msgDb;
  rv = currentMsgFolder->GetMsgDatabase(mCurMsgWindow, getter_AddRefs(msgDb));
  NS_ENSURE_SUCCESS(rv, rv);
  
  msgDb->Commit(nsMsgDBCommitType::kLargeCommit);
  
  //XXX This is where Copy to Local Folders and offline IMAP support will go
  //XXX implement this:
  // if (!IsImapMessage(msgURI))
  //   return;
  
  
  //XXX this is all written in mailWindowOverlay.js line 2339
  //XXX implement IMAP copying stuff.
}

NS_IMETHODIMP
CHMsgService::OnEndAttachments(NSArray* inAttachments)
{
  [mMessageWindowService onAttachmentsLoaded:inAttachments];
}

NS_IMETHODIMP 
CHMsgService::MsgHdrFromURI(const char* aURI, nsIMsgDBHdr** aMsgHdr)
{
  return mMessenger->MsgHdrFromURI(aURI, aMsgHdr);
}

NS_IMETHODIMP 
CHMsgService::GetMessenger(nsIMessenger** aRetVal)
{
  if (!aRetVal || mMessenger)
    return NS_ERROR_NULL_POINTER;
  
  *aRetVal = mMessenger;
  NS_ADDREF(*aRetVal);
  
  return NS_OK;
}

NS_IMETHODIMP 
CHMsgService::InitNewMsgWindow(CHBrowserView* inBrowserView)
{
  nsresult rv;
  
  if (!mMsgWindows)
  {
    rv = NS_NewISupportsArray(getter_AddRefs(mMsgWindows));
    NS_ENSURE_SUCCESS(rv, rv);
  }
  
  nsCOMPtr<nsIMsgWindow> msgWindow = do_CreateInstance(NS_MSGWINDOW_CONTRACTID, &rv);
  if (NS_SUCCEEDED(rv))
  {
    CHMsgHeaderSink* headerSink = new CHMsgHeaderSink(this);
    rv = msgWindow->SetMsgHeaderSink(headerSink);
    if (NS_FAILED(rv))
      printf("ERROR: Could not set the msg header sink: %u\n", rv);
    
    msgWindow->SetStatusFeedback(this);
    
    nsCOMPtr<nsIDOMWindow> domWindow = [inBrowserView getContentWindow];
    nsCOMPtr<nsIDOMWindowInternal> internalDomWindow(do_QueryInterface(domWindow));
    
    rv = msgWindow->SetDOMWindow(internalDomWindow);
    if (NS_FAILED(rv))
    {
#if DEBUG
      printf("ERROR: Could not set the DOM window : %u\n", rv);
#endif
      return NS_ERROR_FAILURE;
    }
    
    // Add the mMsgWindow to the mailSession
    nsCOMPtr<nsIMsgMailSession> mailSession = do_GetService(NS_MSGMAILSESSION_CONTRACTID, &rv);
    if (NS_SUCCEEDED(rv))
    {
      rv = mailSession->AddMsgWindow(msgWindow);
      if (NS_FAILED(rv)) 
      {
#if DEBUG
        printf("ERROR: Could not assign the msg window to the mail session: %u\n", rv);
#endif
        return NS_ERROR_FAILURE;
      }
    }
    
    rv = mMessenger->SetWindow(internalDomWindow, msgWindow);
#if DEBUG
    if (NS_FAILED(rv))
      printf("Could not set the Window of mMessenger!\n");
#endif
    
    mMsgWindows->AppendElement(msgWindow);
    mCurMsgWindow = msgWindow;
  }
  
  return NS_OK;
}

NS_IMETHODIMP
CHMsgService::SetCurrentMsgWindow(CHBrowserView* aBrowserView)
{
  // Find the initialized message window in the array by comparing
  // the |nsIDocShell| pointers of the browser view and message windows.
  nsresult rv;
  nsCOMPtr<nsIMsgWindow> curMsgWindow;
  PRUint32 count;
  PRBool foundMatch = PR_FALSE;
  mMsgWindows->Count(&count);
  
  for (PRUint32 i = 0; i < count && !foundMatch; i++)
  {
    nsCOMPtr<nsISupports> supports;
    rv = mMsgWindows->GetElementAt(i, getter_AddRefs(supports));
    if (NS_SUCCEEDED(rv))
    {
      curMsgWindow = do_QueryInterface(supports);
      if (curMsgWindow)
      {
        nsCOMPtr<nsIDocShell> msgWinDocShell;
        curMsgWindow->GetRootDocShell(getter_AddRefs(msgWinDocShell));
        nsCOMPtr<nsIDocShell> browserViewDocShell = [aBrowserView getDocShell];
        
        if (msgWinDocShell && browserViewDocShell && 
            msgWinDocShell == browserViewDocShell)
        {
          mCurMsgWindow = curMsgWindow;
          foundMatch = PR_TRUE;
        }
      }
    }
  }
  
  if (!foundMatch)
    mCurMsgWindow = nsnull;
  else
  {
    nsCOMPtr<nsIDOMWindow> domWindow = [aBrowserView getContentWindow];
    nsCOMPtr<nsIDOMWindowInternal> internalDomWindow(do_QueryInterface(domWindow));
    mMessenger->SetWindow(internalDomWindow, mCurMsgWindow);
  }
  
  return NS_OK;
}

NS_IMETHODIMP 
CHMsgService::RemoveMsgWindow(CHBrowserView* aBrowserView)
{
  nsresult rv;
  nsCOMPtr<nsIMsgWindow> curMsgWindow;
  PRUint32 count;
  PRBool foundMatch = PR_FALSE;
  mMsgWindows->Count(&count);
  
  //XXX use the nsIMsgSession array...
  
  for (PRUint32 i = 0; i < count && !foundMatch;  i++)
  {
    nsCOMPtr<nsISupports> supports;
    rv = mMsgWindows->GetElementAt(i, getter_AddRefs(supports));
    if (NS_SUCCEEDED(rv))
    {
      curMsgWindow = do_QueryInterface(supports);
      if (curMsgWindow)
      {
        nsCOMPtr<nsIDocShell> msgWinDocShell;
        curMsgWindow->GetRootDocShell(getter_AddRefs(msgWinDocShell));
        nsCOMPtr<nsIDocShell> browserWinDocShell = [aBrowserView getDocShell];
        
        if (msgWinDocShell && browserWinDocShell && 
            msgWinDocShell == browserWinDocShell)
        {
          if (mCurMsgWindow == curMsgWindow)
            mCurMsgWindow = nsnull;
          
          nsCOMPtr<nsIMsgMailSession> msgSession = do_GetService(NS_MSGMAILSESSION_CONTRACTID, &rv);
          NS_ENSURE_SUCCESS(rv, rv);
          
          msgSession->RemoveMsgWindow(curMsgWindow);
          curMsgWindow->CloseWindow();
        }
      }
    }
  }
  
  return NS_OK;
}

NS_IMETHODIMP
CHMsgService::OpenAttachment(const char* aContentType, 
                             const char* aUrl, 
                             const char* aDisplayName, 
                             const char* aMessageUri, 
                             PRBool isExternalAttachment)
{
  nsresult rv = mMessenger->OpenAttachment(aContentType, aUrl, aDisplayName, aMessageUri, isExternalAttachment);
#if DEBUG
  if (NS_FAILED(rv))
    printf("Could not open attachment: %ui\n", rv);
#endif
  
  return rv;
}

#pragma mark -

void 
CHMsgService::OnStartRunningUrl()
{
  [mMessageWindowService onStartTransmission];
}

void 
CHMsgService::OnStopRunningUrl()
{
  [mMessageWindowService onStopTransmission];
}

#pragma mark -

NS_IMETHODIMP 
CHMsgService::HandleMDNResponse(nsIMsgMailNewsUrl* aUrl)
{
  return NS_ERROR_FAILURE;
  if (!aUrl)
    return NS_ERROR_NULL_POINTER;
  
  nsresult rv;
  
  nsCOMPtr<nsIMsgFolder> msgFolder;
  rv = aUrl->GetFolder(getter_AddRefs(msgFolder));
  if (NS_FAILED(rv) || !msgFolder)
    return NS_ERROR_FAILURE;
  
  NSString* curMsgUri = [mMessageWindowService currentMessageUri];
  if (!curMsgUri)
    return NS_ERROR_UNEXPECTED;
  
  /*
   Things to consider in the future:
   if (IsNewsMessage(msgURI))
   return;
   
  // if the message is marked as junk, do NOT attempt to process a return receipt
  // in order to better protect the user
   if (SelectedMessagesAreJunk())
   return;
   */
   
  nsCOMPtr<nsIMimeHeaders> mimeHdr;
  rv = aUrl->GetMimeHeaders(getter_AddRefs(mimeHdr));
  
  // If we didn't get the message id when we downloaded the message header,
  // we cons up an md5: message id. If we've done that, we'll try to extract
  // the message id out of the mime headers for the whole message.
  nsCOMPtr<nsIMsgDBHdr> msgHdr;
  rv = MsgHdrFromURI([curMsgUri cString], getter_AddRefs(msgHdr));
  
  nsXPIDLCString messageId;
  rv = msgHdr->GetMessageId(getter_Copies(messageId));
  if (NS_SUCCEEDED(rv)) 
  {
    // This should be the same as |msgId.split(":")[0] == "md5"|
    if (messageId.Find("md5:", PR_FALSE, 0, messageId.Length()))
    {
      nsXPIDLCString mimeMsgId;
      mimeHdr->ExtractHeader("Message-Id", PR_FALSE, getter_Copies(mimeMsgId));
      if (mimeMsgId)
        msgHdr->SetMessageId(mimeMsgId);
    }
  }
  
  // After a msg is downloaded it's already marked READ at this point so we must check if
  // the msg has a "Disposition-Notification-To" header and no MDN report has been sent yet.
  PRUint32 msgFlags;
  rv = msgHdr->GetFlags(&msgFlags);
  if (NS_SUCCEEDED(rv) && ((msgFlags & MSG_FLAG_IMAP_DELETED) || (msgFlags & MSG_FLAG_MDN_REPORT_SENT)))
    return NS_OK;
  
  nsXPIDLCString DNTHeader;
  mimeHdr->ExtractHeader("Disposition-Notification-To", PR_FALSE, getter_Copies(DNTHeader));
  
  nsXPIDLCString oldDNTHeader;
  mimeHdr->ExtractHeader("Return-Receipt-To", PR_FALSE, getter_Copies(oldDNTHeader));
  if (!DNTHeader || !oldDNTHeader)
    return NS_OK;
  
  nsMsgKey messageKey;
  msgHdr->GetMessageKey(&messageKey);
  
  // Everything looks good so far, let's generate the MDN response.
  nsCOMPtr<nsIMsgMdnGenerator> mdnGenerator(do_CreateInstance("@mozilla.org/messenger-mdn/generator;1", &rv));
  NS_ENSURE_SUCCESS(rv, rv);
  
  mdnGenerator->Process(MDN_DISPOSE_TYPE_DISPLAYED, mCurMsgWindow, msgFolder, messageKey, mimeHdr, PR_FALSE);
  
  // Reset mark msg MDN "Sent" and "Not Needed".
  msgHdr->SetFlags(msgFlags & ~MSG_FLAG_MDN_REPORT_NEEDED);
  // msgHdr.OrFlags(MSG_FLAG_MDN_REPORT_SENT); -> Can't set these..
  
  // Finally commit the DB changes
  nsCOMPtr<nsIMsgDatabase> msgDB;
  rv = msgFolder->GetMsgDatabase(mCurMsgWindow, getter_AddRefs(msgDB));
  if (NS_SUCCEEDED(rv))
    msgDB->Commit(MSG_DB_LARGE_COMMIT);
  
  return NS_OK;
}

#pragma mark -

NS_IMETHODIMP 
CHMsgService::OnItemAdded(nsIRDFResource* parentItem, nsISupports* item)
{
#if DEBUG
  NSLog(@"OnItemAdded...");
#endif
  return NS_OK;
}

NS_IMETHODIMP
CHMsgService::OnItemRemoved(nsIRDFResource* aParentItem, nsISupports* aItem)
{
#if DEBUG
  NSLog(@"OnItemRemoved...");
#endif
  return NS_OK;
}

NS_IMETHODIMP 
CHMsgService::OnItemPropertyChanged(nsIRDFResource* item, 
                                    nsIAtom* property, 
                                    const char* oldValue, 
                                    const char* newValue)
{
#if DEBUG
  NSLog(@"OnItemPropertyChanged: %s -> %s", oldValue, newValue);
#endif
  return NS_OK;
}

NS_IMETHODIMP 
CHMsgService::OnItemIntPropertyChanged(nsIRDFResource* item, 
                                       nsIAtom* property, 
                                       PRInt32 oldValue, 
                                       PRInt32 newValue)
{
  if (!mMessageWindowService)
    return NS_OK;
  
  //XXX Make sure that the item->value is the same as the current folder URI
  if (mCurrentBiffState != newValue)
  {
    mCurrentBiffState = newValue;
    nsresult rv;
    
    // The better way to implement this is to create a simple folder
    // listener class that could notify each message folder that a
    // property has changed, and let that class deal with the notices.

    nsAutoString name;
    rv = property->ToString(name);
    NS_ENSURE_SUCCESS(rv, rv);
    
    if (name == NS_LITERAL_STRING("TotalMessages"))
      [mMessageWindowService onTotalMessagesChanged];
    else if (name == NS_LITERAL_STRING("TotalUnreadMessages"))
      [mMessageWindowService onTotalUnreadMessagesChanged];
    else if (name == NS_LITERAL_STRING("BiffState"))
      [mMessageWindowService onNewMailBiffStateChanged];
  }
  return NS_OK;
}

NS_IMETHODIMP 
CHMsgService::OnItemBoolPropertyChanged(nsIRDFResource* item, 
                                        nsIAtom* property, 
                                        PRBool oldValue, 
                                        PRBool newValue)
{
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP 
CHMsgService::OnItemUnicharPropertyChanged(nsIRDFResource* item, 
                                           nsIAtom* property, 
                                           const PRUnichar* oldValue, 
                                           const PRUnichar* newValue)
{
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP 
CHMsgService::OnItemPropertyFlagChanged(nsIMsgDBHdr* item, 
                                        nsIAtom* property, 
                                        PRUint32 oldFlag, 
                                        PRUint32 newFlag)
{
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP 
CHMsgService::OnItemEvent(nsIMsgFolder* item, nsIAtom* event)
{
  return NS_ERROR_NOT_IMPLEMENTED;
}

#pragma mark -

NS_IMETHODIMP 
CHMsgService::ShowStatusString(const PRUnichar* status)
{
#if DEBUG
  NSLog(@"CHMsgService::ShowStatusString: %@", [NSString stringWithPRUnichars:status]);
#endif
  
  if (!mMessageWindowService)
    return NS_OK;

  [mMessageWindowService onStatusMessageUpdated:[NSString stringWithPRUnichars:status]];
  
  return NS_OK;
}

NS_IMETHODIMP 
CHMsgService::StartMeteors()
{
  if (!mMessageWindowService)
    return NS_OK;
  
  [mMessageWindowService onStartTransmission];
  mIsRunningUri = PR_TRUE;
  return NS_OK;
}

NS_IMETHODIMP 
CHMsgService::StopMeteors()
{
  if (!mMessageWindowService)
    return NS_OK;
  
  [mMessageWindowService onStopTransmission];
  mIsRunningUri = PR_FALSE;
  return NS_OK;
}

NS_IMETHODIMP
CHMsgService::ShowProgress(PRInt32 percent)
{
  return NS_OK;
}

NS_IMETHODIMP
CHMsgService::SetStatusString(const PRUnichar* status)
{
#if DEBUG
  NSLog(@"CHMsgService::SetStatusString() -> %@", [NSString stringWithPRUnichars:status]);
#endif
  return NS_OK;
}

NS_IMETHODIMP
CHMsgService::SetDocShell(nsIDocShell* shell, nsIDOMWindow* window)
{
  return NS_OK;
}

NS_IMETHODIMP
CHMsgService::CloseWindow()
{
  return NS_OK;
}

